/*
** Copyright (C) 2009 Zhang Cong <ftofficer@ftofficer.com>
**  
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**  
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**  
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**  
*/

/*
 * oish is an interactive shell to operate an OI-based device.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif // HAVE_CONFIG_H

#include <stdio.h>
#include <string.h>

#include <liboi.h>

void log_func(const char* file, int line, const char* msg)
{
    const char* slash;
    const char* basename;

    slash = strrchr(file, '/');
    if ( slash == NULL )
        basename = file;
    else
        basename = slash + 1;

    fprintf(stderr, "[%s:%d] %s\n", basename, line, msg);
}

liboi_err_t oish_show_dev_info(oi_device* dev)
{
    oi_device_info dev_info;
    liboi_err_t error = LIBOI_OK;
    int i=0;

    error = oi_device_get_info(dev, &dev_info);
    if ( LIBOI_OK != error )
    {
        fprintf(stderr, "Unable to get OI device infomation: [%d] %s\n",
                error, liboi_strerror(error));
        return error;
    }

    printf("Connected to device: openinkpot %s (%s)\n",
           dev_info.oi_version, dev_info.model);
    printf("Device Key: ");
    for ( i=0; i<dev_info.dev_key_len; ++i )
        printf("%02X", (unsigned char)(dev_info.dev_key[i]));
    printf("\n");

    return LIBOI_OK;
}

liboi_err_t oish_show_sd_root(oi_device* dev)
{
    struct data_buffer stdout_ = {0};
    struct data_buffer stderr_ = {0};
    int exit_code = 0;
    liboi_err_t err_no = LIBOI_OK;

    // Determine SD card status.
    err_no = oi_exec_in_device(dev, "df", NULL,
                               &exit_code, &stdout_, &stderr_);

    if ( err_no != LIBOI_OK || exit_code != 0 )
    {
        fprintf(stderr, "Unable to determine SD status: %d, exit_code=%d, stderr=%s\n",
                err_no, exit_code, stderr_.data);
        oi_free_data_buffer(&stdout_);
        oi_free_data_buffer(&stderr_);
        return err_no;
    }

    oi_free_data_buffer(&stderr_);
    if ( strstr(stdout_.data, "/media/sd") == NULL )
    {
        oi_free_data_buffer(&stdout_);
        printf("SD card was not connected.\n");
        return LIBOI_OK;
    }

    oi_free_data_buffer(&stdout_);

    // Get SD card root contents.
    err_no = oi_exec_in_device(dev, "ls -1A /media/sd", NULL, 
                               &exit_code, &stdout_, &stderr_);

    if ( err_no != LIBOI_OK || exit_code != 0 )
    {
        fprintf(stderr, "Unable to list SD content: %d, exit_code=%d, stderr=%s\n",
                err_no, exit_code, stderr_.data);
        oi_free_data_buffer(&stdout_);
        oi_free_data_buffer(&stderr_);
        return err_no;
    }
    
    printf("Content of SD card:\n");
    printf("%s\n", stdout_.data);

    oi_free_data_buffer(&stdout_);
    oi_free_data_buffer(&stderr_);

    return LIBOI_OK;
}

static void write_result(liboi_err_t err)
{
    if ( err == LIBOI_OK )
        printf("OK\n");
    else
    {
        printf("FAIL: %d: %s\n", err, liboi_strerror(err));
    }
}

int main(int argc, char* argv[])
{
    oi_device_location loc;
    oi_device* dev = 0;
    liboi_err_t error = LIBOI_OK;
	char* host_path = NULL;
	char* dev_path = NULL;

	liboi_init();

    oi_set_log_func(log_func);
    // TODO: Change this to command line option:
    //   -d = debug
    //   -v = info
    //   <default> = warn
    //   -q = no_log
    oi_set_log_level(LOG_DEBUG);

    loc.type = OI_DEVICE_SSH_CONNECTED;
    // TODO: Change this to configuable.
    loc.address = "192.168.111.1:22";

	printf("Will connect device at %s...\n", loc.address);
    error = oi_device_connect(&loc, &dev);
    if ( error != LIBOI_OK )
    {
        fprintf(stderr, "Unable to connect to device %s: [%d] %s.\n",
                loc.address, error, liboi_strerror(error));
        return 0;
    }

    printf("\nWill show device information...\n");
    error = oish_show_dev_info(dev);
    write_result(error);

    printf("\nWill show SD card root content...\n");
    error = oish_show_sd_root(dev);
    write_result(error);

	dev_path = "/etc/iplinux_version";
#ifdef WIN32
	host_path = "C:\\iplinux_version";
#else // WIN32
	host_path = "/tmp/iplinux_version";
#endif // WIN32
    printf("\nWill copy %s from device to host...\n", dev_path);
    error = oi_get_file(dev, dev_path, host_path);    
    write_result(error);

	dev_path = "/etc/inputrc";
#ifdef WIN32
	host_path = "C:\\inputrc";
#else // WIN32
	host_path = "/tmp/inputrc";
#endif // WIN32
    printf("\nWill copy a not exist file %s from device to host...\n", dev_path);
    error = oi_get_file(dev, dev_path, host_path);
    write_result(error);

	dev_path = "/etc/openinkpot-version";
#ifdef WIN32
	host_path = "C:\\this.should.not.exist\\openinkpot-version";
#else // WIN32
	host_path = "/tmp/this.should.not.exist/openinkpot-version";
#endif // WIN32
    printf("\nWill copy a file from device to a host folder not accessable...\n");
    error = oi_get_file(dev, dev_path, host_path);
    write_result(error);

#ifdef WIN32
	host_path = "C:\\WINDOWS\\explorer.exe";
#else // WIN32
	host_path = "/etc/issue";
#endif // WIN32
	dev_path = "/media/sd/test-doc.txt";
    printf("\nWill copy %s to device %s...\n", host_path, dev_path);
    error = oi_put_file(dev, host_path, dev_path);
    write_result(error);

#ifdef WIN32
	host_path = "C:\\WINDOWS\\explorer.exe";
#else // WIN32
	host_path = "/etc/issue";
#endif // WIN32
	dev_path = "/media/sd/";
    printf("\nWill copy %s to device folder %s...\n", host_path, dev_path);
    error = oi_put_file(dev, host_path, dev_path);
    write_result(error);

#ifdef WIN32
	host_path = "C:\\this.file.does.not.exist.txt";
#else // WIN32
	host_path = "/etc/this.does.not.exit";
#endif // WIN32
	dev_path = "/media/sd/test_doc.txt";
    printf("\nWill copy a not exist file to device...\n");
    error = oi_put_file(dev, host_path, dev_path);
    write_result(error);

#ifdef WIN32
	host_path = "C:\\WINDOWS\\explorer.exe";
#else // WIN32
	host_path = "/etc/issue";
#endif // WIN32
	dev_path = "/this/path/does/not/exist";
    printf("\nWill copy a file to device not exit path...\n");
    error = oi_put_file(dev, host_path, dev_path);
    write_result(error);
    
    printf("\nWill disconnect device...\n");
    error = oi_device_disconnect(dev);
    if ( error != LIBOI_OK )
    {
        fprintf(stderr, "Unable to disconnect device %s: [%d] %s.\n",
                dev->dev_loc.address, error, liboi_strerror(error));
    }

    oi_device_free(dev);

	liboi_cleanup();
    
    return 0;
}


